package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.constant.EsNormalConstant;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.dto.DeleteDTO;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaySheetTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.UnitEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataListSearchHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.DataDetailPojo;
import com.xbongbong.paas.pojo.DetailTabPojo;
import com.xbongbong.paas.pojo.DetailTitlePojo;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.FormTitlePoJoSub;
import com.xbongbong.paas.pojo.PrePaymentBalanceListPojo;
import com.xbongbong.paas.pojo.ShareConditionFormatPojo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.SummaryExtraDataPoJo;
import com.xbongbong.paas.pojo.WorkFlowPojo;
import com.xbongbong.paas.pojo.dto.AggSumDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataGetDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.AggSumVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.PaySheetFromBalanceListVO;
import com.xbongbong.paas.pojo.vo.PrePayBalanceListVO;
import com.xbongbong.paas.pojo.vo.PrePaymentBalanceListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.explain.FormDataListFormExplainHandleName;
import com.xbongbong.pro.appdetail.pojo.MobileDetailDirectBlockPojo;
import com.xbongbong.pro.appdetail.pojo.MobileDetailScriptPojo;
import com.xbongbong.pro.appdetail.pojo.MobileDetailSpecialInfoPojo;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ApprovalErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessTypeErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.FundAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.form.pojo.TopPermissionsPoJo;
import com.xbongbong.pro.formdata.pojo.LinkBusinessSinglePojo;
import com.xbongbong.pro.formdata.pojo.dto.FormDataDetailDTO;
import com.xbongbong.pro.formdata.pojo.vo.FormDataDetailVO;
import com.xbongbong.pro.formdata.pojo.vo.MobileFormCommonDetailVO;
import com.xbongbong.pro.formexplain.pojo.HandleExplainPojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.vo.HandlerExplainVO;
import com.xbongbong.pro.paybalance.pojo.dto.PaySheetFromBalanceDTO;
import com.xbongbong.pro.permission.pojo.dto.VerifyViewPermissionDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.ChartQueryHelp;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.pro.sheet.pojo.dto.SheetDeleteHandleRelateDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.PayBalanceEntity;
import com.xbongbong.saas.domain.entity.PayBalanceUserEntity;
import com.xbongbong.saas.domain.entity.SupplierUserEntity;
import com.xbongbong.saas.domain.entity.ext.SupplierEntityExt;
import com.xbongbong.saas.enums.BusinessDetailButtonEnum;
import com.xbongbong.saas.enums.BusinessDetailTabEnum;
import com.xbongbong.saas.enums.MobileDetailBottomOperationEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.PayBalanceEnum;
import com.xbongbong.saas.enums.SaasButtonEnum;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ManagementButtomEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.help.ProDetailHandlerHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PayBalanceModel;
import com.xbongbong.saas.model.PayBalanceUserModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.model.SupplierUserModel;
import com.xbongbong.saas.service.PayBalanceService;
import com.xbongbong.saas.service.SaasListService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.service.toolbox.help.SaasListDataPermissionHelp;
import com.xbongbong.sys.help.ProPermissionHelp;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 徐俊杰
 * @date 2020/2/25 10:31
 * @since v1.0
 */
@Service("payBalanceService")
public class PayBalanceServiceImpl implements PayBalanceService {
    public static final Logger LOG = LoggerFactory.getLogger(PayBalanceServiceImpl.class);
    @Resource
    private SaasListDataPermissionHelp saasListDataPermissionHelp;
    @Resource
    private FormDataListSearchHelp formDataListSearchHelp;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private FormDataListFormExplainHandleName formDataListFormExplainHandleName;
    @Resource
    private PayBalanceModel payBalanceModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private SupplierUserModel supplierUserModel;
    @Resource
    private PayBalanceUserModel payBalanceUserModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private ProDetailHandlerHelp proDetailHandlerHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private SaasListService saasListService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PayBalanceService payBalanceService;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private ChartQueryHelp chartQueryHelp;
    @Resource
    private FormHelp formHelp;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public PrePayBalanceListVO prepayBalanceList(FormDataListDTO formDataListDTO) throws XbbException {
        PrePaymentBalanceListPojo prePayBalanceListPojo =  prePayBalanceCommonList(formDataListDTO);
        
        PrePayBalanceListVO prePayBalanceListVO = new PrePayBalanceListVO();
        PageHelper pageHelper = new PageHelper(formDataListDTO.getPage(), formDataListDTO.getPageSize());
        pageHelper.setRowsCount( prePayBalanceListPojo.getRowsCount());
        prePayBalanceListVO.setPaasFormDataESList(prePayBalanceListPojo.getResultList());
        prePayBalanceListVO.setPageHelper(pageHelper);
        prePayBalanceListVO.setBusinessType(formDataListDTO.getBusinessType());

        prePayBalanceListVO.setForm(prePayBalanceListPojo.getForm());
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO, false);
        handlerExplainDTO.setExplainList(prePayBalanceListPojo.getExplainList());
        handlerExplainDTO.setPaasFormEntityExt(prePayBalanceListPojo.getForm());
        HandlerExplainVO handlerExplainVO = formDataListFormExplainHandleName.handleExplain(handlerExplainDTO);
        if (handlerExplainVO == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
        prePayBalanceListVO.setHeadList(handlerExplainVO.getHeadList());
        prePayBalanceListVO.setExplainMap(formDataListDTO.getExplainMap());
        prePayBalanceListVO.setSecondaryExplainMap(prePayBalanceListPojo.getSecondaryExplainMap());
        // 设置列表页操作栏
        saasListHelp.setPrePayBalanceOption(prePayBalanceListVO, formDataListDTO);
        prePayBalanceListVO.setTopPermissions(prePayBalanceListPojo.getTopPermissions());
        prePayBalanceListVO.setBottomPermissions(prePayBalanceListPojo.getBottomPermissions());
        return prePayBalanceListVO;
    }

    @Override
    public ListAppVO prepayBalanceAppList(FormDataListDTO formDataListDTO) throws XbbException {
        PrePaymentBalanceListPojo prePayBalanceListPojo = prePayBalanceCommonList(formDataListDTO);
        ListAppVO listAppVO = new ListAppVO();
        Integer rowsCount = prePayBalanceListPojo.getRowsCount();
        listAppVO.setTotalCount(rowsCount);
        listAppVO.setBusinessType(formDataListDTO.getBusinessType());
        List<AppListPojo> list = new ArrayList<>();
        if (rowsCount != null && rowsCount != 0) {
            List<PayBalanceEntity> resultList = prePayBalanceListPojo.getResultList();
            PaasFormEntityExt form = prePayBalanceListPojo.getForm();
            JSONArray summaryArray = form.getSummaryList();
            JSONArray titleArray = JSONArray.parseArray(form.getCustomTitle());
            for (PayBalanceEntity payBalanceEntity : resultList) {
                JSONObject data = payBalanceEntity.getData();
                //摘要
                List<SummaryDataPoJo> summaryList = new ArrayList<>();
                if(CollectionsUtil.isNotEmpty(summaryArray)){
                    for (int i = 0; i < summaryArray.size(); i++) {
                        SummaryDataPoJo summaryDataPoJo   = summaryArray.getJSONObject(i).toJavaObject(SummaryDataPoJo.class);
                        Object value = data.get(summaryDataPoJo.getAttr());
                        if(value != null){
                            summaryDataPoJo.setValue(Collections.singletonList(value.toString()));
                            summaryList.add(summaryDataPoJo);
                        }
                    }
                }
                //标题
                List<FormTitlePoJo> titleList = new ArrayList<>();
                if(CollectionsUtil.isNotEmpty(titleArray)){
                    for (int i = 0; i < titleArray.size(); i++) {
                        FormTitlePoJoSub formTitlePoJoSub =  titleArray.getJSONObject(i).toJavaObject(FormTitlePoJoSub.class);
                        JSONArray jSONArray  = data.getJSONArray(formTitlePoJoSub.getAttr());
                        if(CollectionsUtil.isNotEmpty(jSONArray)){
                            //应该按照类型解析  (关联业务单选)
                            LinkBusinessSinglePojo  linkBusinessSinglePojo  = jSONArray.getJSONObject(0).toJavaObject(LinkBusinessSinglePojo.class);
                            Long id = linkBusinessSinglePojo.getId();
                            String value = linkBusinessSinglePojo.getName();
                            if(id != null && value != null){
                                formTitlePoJoSub.setId(id);
                                formTitlePoJoSub.setValue(Collections.singletonList(value));
                                titleList.add(formTitlePoJoSub);
                            }
                        }
                    }
                }
                //others
                JSONObject others = new JSONObject();
                String advancePayBalance = data.getString(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr());
                if(StringUtil.isNotEmpty(advancePayBalance)){
                    advancePayBalance +=  UnitEnum.MONEY.getName();
                }
                others.put("amount", advancePayBalance);
                JSONObject superScript = new JSONObject();
                List<SummaryDataPoJo> lablesList = new ArrayList<>();
                list.add(new AppListPojo(payBalanceEntity.getId(), titleList, summaryList, superScript, lablesList, others, payBalanceEntity.getAppId(), payBalanceEntity.getMenuId(), payBalanceEntity.getFormId()));
            }
        } else {
            rowsCount = 0;
        }
        listAppVO.setList(list);
        listAppVO.setTotalCount(rowsCount);
        //权限
        boolean addPermission = false;
        List<ButtonPojo> buttonPojoList = prePayBalanceListPojo.getTopPermissions();
        if (Objects.nonNull(buttonPojoList) && !buttonPojoList.isEmpty()) {
            for (ButtonPojo buttonPojo : buttonPojoList) {
                if (Objects.nonNull(buttonPojo) && Objects.equals(buttonPojo.getAttr(), SaasButtonEnum.ADD.getAttr())) {
                    addPermission = true;
                }
            }
        }
        listAppVO.setAddPermission(addPermission);
        return listAppVO;
    }

    @Override
    public MobileFormCommonDetailVO getMoblieDetail(FormDataGetDTO formDataGetDTO) throws XbbException {
        MobileFormCommonDetailVO   mobileFormCommonDetailVO = new MobileFormCommonDetailVO();
        // 查看权限校验
        VerifyViewPermissionDTO verifyViewPermissionDTO = new VerifyViewPermissionDTO();
        BeanUtil.copyProperties(formDataGetDTO, verifyViewPermissionDTO);
        ProPermissionHelp.verifyQueryPermission(verifyViewPermissionDTO);
        String corpid = formDataGetDTO.getCorpid();
        PayBalanceEntity payBalanceEntity = payBalanceModel.getById(formDataGetDTO.getDataId(), corpid);
        if (payBalanceEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long formId = payBalanceEntity.getFormId();
        //验证表单和解释
        PaasFormEntityExt paasFormEntity = varifyFormAndExplain(corpid, formId);
        //设置客户名称
        Long supplierId = payBalanceEntity.getSupplierId();
        SupplierEntityExt supplierEntity = supplierModel.getByKey(supplierId, corpid);
        JSONObject data = (JSONObject) JSONObject.toJSON(payBalanceEntity);
        String supplierName = null;
        if(supplierEntity != null){
            supplierName = supplierEntity.getData().getString(SupplierEnum.SUPPLIER_NAME.getAttr());
            data.remove("data");
            data.remove("sourceData");
            data.put(PayBalanceEnum.SUPPLIER_NAME.getAttr(),supplierName);
        }
        mobileFormCommonDetailVO.setData(data);
        mobileFormCommonDetailVO.setPaasFormEntity(paasFormEntity);
        //titleLis标题
        FormTitlePoJo formTitlePoJo = new FormTitlePoJo();
        formTitlePoJo.setAttr(PayBalanceEnum.SUPPLIER_ID.getAttr());
        formTitlePoJo.setAttrName(PayBalanceEnum.SUPPLIER_ID.getAttrName());
        String value = data.getString(PayBalanceEnum.SUPPLIER_NAME.getAttr());
        if(value == null){
            value = "";
        }
        formTitlePoJo.setValue(Arrays.asList(value));
        mobileFormCommonDetailVO.setTitleList(Arrays.asList(formTitlePoJo));
        //摘要
        List<SummaryDataPoJo> summaryList = new ArrayList<>();
        SummaryExtraDataPoJo summaryExtraDataPoJo = new SummaryExtraDataPoJo(supplierId,XbbRefTypeEnum.SUPPLIER.getCode());
        JSONObject summaryExtraDataJsonObject = (JSONObject) JSON.toJSON(summaryExtraDataPoJo);
        SummaryDataPoJo  supplierSummaryDataPoJo = new SummaryDataPoJo(PayBalanceEnum.SUPPLIER_ID.getAttr(),PayBalanceEnum.SUPPLIER_ID.getAttrName(),PayBalanceEnum.SUPPLIER_ID.getFieldType(),Arrays.asList(data.getString(PayBalanceEnum.SUPPLIER_NAME.getAttr())),summaryExtraDataJsonObject);
        summaryList.add(supplierSummaryDataPoJo);
        mobileFormCommonDetailVO.setSummaryList(summaryList);
        //右侧
        MobileDetailSpecialInfoPojo specialInfoPojo = new MobileDetailSpecialInfoPojo();
        List<MobileDetailScriptPojo> script = new ArrayList<>();
        MobileDetailScriptPojo pojo = new MobileDetailScriptPojo();
        //精度
        Integer accuracy =  getAccuracy(corpid);
        Double advancePayBalance = payBalanceEntity.getAdvancePayBalance();
        Object moneyStr =  AttrDecimalPrecisionHelper.parseThousandth(advancePayBalance,accuracy);
        pojo.setMoneyScript(moneyStr + UnitEnum.MONEY.getName());
        script.add(pojo);
        specialInfoPojo.setScript(script);
        mobileFormCommonDetailVO.setRightSpecialInfo(specialInfoPojo);
        //tab
        UserVO loginUser = formDataGetDTO.getLoginUser();
        List<DetailTabPojo> tabList = getDetailTabPojos(XbbRefTypeEnum.PREPAY_BALANCE.getCode(),loginUser,PlatFormEnum.DINGTALK,corpid,formId);
        mobileFormCommonDetailVO.setTabList(tabList);
        //权限
        //只有当预付款余额>0，且待核销采购合同个数大于0才可以核销
        Map<Long, Integer> purchaseCountMap = getPurchaseCountBySupplier(corpid, Arrays.asList(supplierId));
        Integer puchaseCount = purchaseCountMap.get(supplierId);
        boolean purchaseCountB = puchaseCount != null && puchaseCount > 0;
        boolean advanceB = advancePayBalance != null && advancePayBalance > 0;
        List<TopPermissionsPoJo> topPermissions = new ArrayList<>();
        if(advanceB ){
            Set<String> permSet = loginUser.getPermSet();
            if(purchaseCountB ){
                if (permSet.contains(ProPermissionAliasEnum.PAY_SHEET_ADD.getAlias()) && !Objects.equals(ProPermissionAliasEnum.PAY_SHEET_ADD.getAlias(), StringConstant.POSITIVE_NUMBER)) {
                    TopPermissionsPoJo topPermissionsPoJo = new TopPermissionsPoJo();
                    MobileDetailBottomOperationEnum mobileDetailBottomOperationEnum = MobileDetailBottomOperationEnum.PREPAY_BALANCE_UPDATE;
                    topPermissionsPoJo.setAttr(mobileDetailBottomOperationEnum.getAttr());
                    topPermissionsPoJo.setBtnType(mobileDetailBottomOperationEnum.getBtnType());
                    topPermissionsPoJo.setBusinessType(mobileDetailBottomOperationEnum.getBusinessType());
                    topPermissionsPoJo.setValue(mobileDetailBottomOperationEnum.getValue());
                    topPermissions.add(topPermissionsPoJo);
                }
            }
            if (permSet.contains(ProPermissionAliasEnum.PAY_SHEET_RED.getAlias()) && !Objects.equals(ProPermissionAliasEnum.PAY_SHEET_RED.getAlias(), StringConstant.POSITIVE_NUMBER)) {
                TopPermissionsPoJo topPermissionsPoJo = new TopPermissionsPoJo();
                MobileDetailBottomOperationEnum mobileDetailBottomOperationEnum = MobileDetailBottomOperationEnum.PREPAY_BALANCE_RED;
                topPermissionsPoJo.setAttr(mobileDetailBottomOperationEnum.getAttr());
                topPermissionsPoJo.setBtnType(mobileDetailBottomOperationEnum.getBtnType());
                topPermissionsPoJo.setBusinessType(mobileDetailBottomOperationEnum.getBusinessType());
                topPermissionsPoJo.setValue(mobileDetailBottomOperationEnum.getValue());
                topPermissions.add(topPermissionsPoJo);
            }
        }
        MobileDetailBottomOperationEnum mobileDetailBottomOperationEnum = MobileDetailBottomOperationEnum.PREPAY_BALANCE_DEL;
        TopPermissionsPoJo topPermissionsPoJo = new TopPermissionsPoJo.Builder().attr(mobileDetailBottomOperationEnum.getAttr())
                .btnType(mobileDetailBottomOperationEnum.getBtnType()).businessType(mobileDetailBottomOperationEnum.getBusinessType())
                .value(mobileDetailBottomOperationEnum.getValue()).build();
        topPermissions.add(topPermissionsPoJo);
        mobileFormCommonDetailVO.setTopPermissions(topPermissions);

        //处理bottomBlockInfo
        JSONArray bottomBlockInfo = new JSONArray();
        bottomBlockInfo.add(new MobileDetailDirectBlockPojo(supplierId, XbbRefTypeEnum.SUPPLIER.getCode(), supplierName));
        mobileFormCommonDetailVO.setBottomBlockInfo(bottomBlockInfo);
        return mobileFormCommonDetailVO;
    }

    @Override
    public FormDataDetailVO getWebDetail(FormDataDetailDTO formDataDetailDTO) throws XbbException {
        FormDataDetailVO formDataDetailVO = new FormDataDetailVO();
        FormDataGetDTO formDataGetDTO = new FormDataGetDTO();
        BeanUtil.copyProperties(formDataDetailDTO,formDataGetDTO);
        String corpid = formDataGetDTO.getCorpid();
        PayBalanceEntity payBalanceEntity = payBalanceModel.getById(formDataGetDTO.getDataId(), corpid);
        if (payBalanceEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        //
        Long formId = payBalanceEntity.getFormId();
        //验证表单和解释
        PaasFormEntityExt paasFormEntity = varifyFormAndExplain(corpid, formId);
        //设置供应商名称
        Long supplierId = payBalanceEntity.getSupplierId();
        SupplierEntityExt supplierEntity = supplierModel.getByKey(supplierId, corpid);
        String supplierName = "";
        if(supplierEntity != null){
            supplierName = supplierEntity.getData().getString(SupplierEnum.SUPPLIER_NAME.getAttr());
        }
        formDataDetailVO.setTab(getDetailTabPojos(XbbRefTypeEnum.PREPAY_BALANCE.getCode(),formDataDetailDTO.getLoginUser(),PlatFormEnum.WEB,corpid,formId));
        PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
        BeanUtil.copyProperties(paasFormEntity,paasFormEntityExt);
        formDataDetailVO.setPaasFormEntityExt(paasFormEntityExt);
        //副标题
        JSONArray secondTitle = new JSONArray();
        List<LinkBusinessSinglePojo> supplierLink = getSupplierLinkBusinessSinglePojos(supplierId, supplierName);
        secondTitle.add( ExplainUtil.getSecondTitleObj(false, PayBalanceEnum.SUPPLIER_ID.getAttrName(), supplierLink,"though"));
        //金额的处理
        //精度
        Integer accuracy =  getAccuracy(corpid);
        Double advancePayBalance = payBalanceEntity.getAdvancePayBalance();
        Object moneyStr =  AttrDecimalPrecisionHelper.parseThousandth(advancePayBalance,accuracy);
        secondTitle.add( ExplainUtil.getSecondTitleObj(false, PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttrName(), moneyStr + UnitEnum.MONEY.getName()));
        //头部信息（包含操作）
        DataDetailPojo dataDetailPojo = new DataDetailPojo();
        //标题
        DetailTitlePojo title = new DetailTitlePojo();
        title.setName(supplierName);
        dataDetailPojo.setTitle(title);
        dataDetailPojo.setSecondTitle(secondTitle);
        //
        List<WorkFlowPojo> workFlowPojoList = new ArrayList<>();
        //只有当预收款余额>0，切待核销合同个数大于0才可以核销
        Map<Long, Integer> purchaseCountMap = getPurchaseCountBySupplier(corpid, Collections.singletonList(supplierId));
        Integer purchaseCount = purchaseCountMap.get(supplierId);
        boolean purchaseCountB = purchaseCount != null && purchaseCount > 0;
        boolean advanceB = advancePayBalance != null && advancePayBalance > 0;
        if(advanceB ){
            UserVO loginUser = formDataGetDTO.getLoginUser();
            Set<String> permSet = loginUser.getPermSet();
            if (purchaseCountB) {
                //核销
                if (permSet.contains(ProPermissionAliasEnum.PAY_SHEET_ADD.getAlias()) && !Objects.equals(ProPermissionAliasEnum.PAY_SHEET_ADD.getAlias(), StringConstant.POSITIVE_NUMBER)) {
                    setWorkFlowPojo(workFlowPojoList, BusinessDetailButtonEnum.PREPAY_BALANCE_UPDATE);
                }
            }
            //红冲退款
            if (permSet.contains(ProPermissionAliasEnum.PAY_SHEET_RED.getAlias()) && !Objects.equals(ProPermissionAliasEnum.PAY_SHEET_RED.getAlias(), StringConstant.POSITIVE_NUMBER)) {
                setWorkFlowPojo(workFlowPojoList, BusinessDetailButtonEnum.PREPAY_BALANCE_RED);
            }
        }
        //增加一个校正按钮
        ManagementButtomEnum prepaymentBalanceFix = ManagementButtomEnum.PREPAY_BALANCE_FIX;
        WorkFlowPojo workFlowPojo = new WorkFlowPojo();
        workFlowPojo.setAttr(prepaymentBalanceFix.getAttr());
        workFlowPojo.setBtnType(prepaymentBalanceFix.getBtuType());
        workFlowPojo.setBusinessType(prepaymentBalanceFix.getBusinessType());
        workFlowPojo.setValue(prepaymentBalanceFix.getValue());
        workFlowPojoList.add(workFlowPojo);
        dataDetailPojo.setWorkFlow(workFlowPojoList);
        //按钮
        ButtonPojo buttonPojo = new ButtonPojo();
        SaasButtonEnum saasButtonEnum = BusinessDetailButtonEnum.PREPAY_BALANCE_DEL.getAnEnum();
        BeanUtil.copyProperties(saasButtonEnum, buttonPojo);
        List<ButtonPojo> buttonPojoList = new ArrayList<>();
        buttonPojoList.add(buttonPojo);
        dataDetailPojo.setButton(buttonPojoList);
        dataDetailPojo.setTags(new JSONArray());
        dataDetailPojo.setTabSortPermission(true);
        dataDetailPojo.setDial(new ArrayList<>());
        formDataDetailVO.setHead(dataDetailPojo);
        return formDataDetailVO;
    }

    @Override
    public PaySheetFromBalanceListVO paySheetFromBalanceList(PaySheetFromBalanceDTO paySheetFromBalanceDTO) throws XbbException {
        String corpid = paySheetFromBalanceDTO.getCorpid();
        PaasFormEntityExt paasForm = paasFormModel.getByBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode(), corpid);
        if(paasForm == null){
            throw  new XbbException(ApprovalErrorCodeEnum.API_ERROR_209012);
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(paasForm.getId(), corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        paySheetFromBalanceDTO.setBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
        paySheetFromBalanceDTO.setSubBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
        paySheetFromBalanceDTO.setAppId(paasForm.getAppId());
        paySheetFromBalanceDTO.setFormId(paasForm.getId());
        paySheetFromBalanceDTO.setPlatform("web");
        //设置explains
        formDataListSearchHelp.handlExplains(paySheetFromBalanceDTO,paasForm);
        List<ConditionsEntityExt> conditionList = paySheetFromBalanceDTO.getConditions();
        conditionList.add(new ConditionsEntityExt(PaySheetEnum.LINK_SUPPLIER.getAttr(), "", FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), ConditionEnum.EQUAL.getSymbol(), Collections.singletonList(paySheetFromBalanceDTO.getSupplierId())));
        //预付款、预付款核销、红冲预付款余额
        conditionList.add(new ConditionsEntityExt(PaySheetEnum.PAY_SHEET_TYPE.getAttr(), "", FieldTypeEnum.TEXT.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(PaySheetTypeEnum.PREPAY.getCode(), PaySheetTypeEnum.WRITE_OFF_PREPAY.getCode(), PaySheetTypeEnum.RED_PREPAY.getCode())));
        //过滤审批中的数据（后面有统一的处理）
        FormDataListDTO formDataListDTO = new FormDataListDTO();
        BeanUtil.copyProperties(paySheetFromBalanceDTO,formDataListDTO);
        List<String> fieldList = Arrays.asList(PaySheetEnum.REAL_PAY_TIME.getAttr(),  PaySheetEnum.AMOUNT.getAttr(), PaySheetEnum.WRITE_OFF_AMOUNT.getAttr(), PaySheetEnum.PAY_SHEET_TYPE.getAttr(), PaySheetEnum.PAY_PLAN_NO.getAttr());
        formDataListDTO.setFieldList(fieldList);
        //排序  按照添加时间正序  编辑金额不允许修改  格式 {field: "addTime", sort: "asc"}
        Map<String, String> sortMap = new HashMap<>(2);
        sortMap.put("field",PaySheetEnum.ADD_TIME.getAttr());
        sortMap.put("sort","asc");
        formDataListDTO.setSortMap(sortMap);
        FormDataListDTO newFormDataListDTO = new FormDataListDTO();
        BeanUtil.copyProperties(paySheetFromBalanceDTO,newFormDataListDTO);
        List<ConditionsEntityExt> conditions = (List<ConditionsEntityExt>) CloneUtil.deepClone(conditionList);
        newFormDataListDTO.setConditions(conditions);
        PaasFormDataEsListVO formDataListVO = saasListService.paySheetList(formDataListDTO);
        List<FieldAttrEntity> headList = formDataListVO.getHeadList();
        List<FieldAttrEntity> newHeadList = new ArrayList<>();
        for (FieldAttrEntity fieldAttrEntity : headList) {
            if(fieldList.contains(fieldAttrEntity.getAttr())){
                newHeadList.add(fieldAttrEntity);
            }
        }
        //添加预收款余额字段
        FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
        fieldAttrEntity.setAttr(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr());
        fieldAttrEntity.setAttrName(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttrName());
        fieldAttrEntity.setFieldType(PayBalanceEnum.ADVANCE_PAY_BALANCE.getFieldType());
        newHeadList.add(fieldAttrEntity);
        //预收款余额
        double  advancePayBalance = 0;
        double  amount= 0;
        double  writeOffAmount= 0;
        //从第二页开始要计算前面的预付款余额
        Integer page = paySheetFromBalanceDTO.getPage();
        if(page != null && page >1){
            List<PaasFormDataEntityExt> paasFormDataESList = formDataListVO.getPaasFormDataESList();
            if(CollectionsUtil.isNotEmpty(paasFormDataESList)){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                //计算本页之前的数据
                PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataESList.get(0);
                boolQueryBuilder.filter(rangeQuery(FieldTypeEnum.DATAID.getAlias()).lt( paasFormDataEntityExt.getDataId()));
                //只要无子和父的
                boolQueryBuilder.filter(termsQuery(BasicConstant.ALONE, SheetAloneEnum.getNotChildCodeList()));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
                //预付款流水
                NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET;
                paasFormDataEsModel.getSearchRequest(newFormDataListDTO, indexTypeEnum, sourceBuilder, boolQueryBuilder);
                nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
                NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
                List<AggSumDTO> sumList = new ArrayList<>();
                // 统计字段
                //付款金额
                AggSumDTO amountAggSumDTO = getAggSumDTO(PaySheetEnum.AMOUNT);
                sumList.add(amountAggSumDTO);
                AggSumDTO writeOffAmountAggSumDTO = getAggSumDTO(PaySheetEnum.WRITE_OFF_AMOUNT);
                //核销金额
                sumList.add(writeOffAmountAggSumDTO);
                List<AggSumVO> aggSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, searchQuery);
                for (AggSumVO aggSumVO : aggSumList) {
                    double value = Double.parseDouble(aggSumVO.getValue().toString());
                    if(Objects.equals(PaySheetEnum.AMOUNT.getAttr(), aggSumVO.getAttr())){
                        amount = Arith.add(amount, value);
                        advancePayBalance = Arith.add(advancePayBalance, value);
                    }else if(Objects.equals(PaySheetEnum.WRITE_OFF_AMOUNT.getAttr(), aggSumVO.getAttr())){
                        writeOffAmount = Arith.add(writeOffAmount, value);
                        advancePayBalance = Arith.sub(advancePayBalance, value);
                    }
                }
            }
        }
        List<PaasFormDataEntityExt> paasFormDataESList = formDataListVO.getPaasFormDataESList();
        Integer accuracy = formDataListVO.getExplainMap().get((PaySheetEnum.AMOUNT.getAttr())).getAccuracy();
        if(CollectionsUtil.isNotEmpty(paasFormDataESList)){
            for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                JSONObject data  = paasFormDataEntityExt.getData();
                JSONObject sourceData  = paasFormDataEntityExt.getSourceData();
                //原值
                advancePayBalance = Arith.add(advancePayBalance,getDouble(sourceData.getString(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr())) );
                //回款金额
                double innerAmount = getDouble(sourceData.getString(PaySheetEnum.AMOUNT.getAttr()));
                amount = Arith.add(amount, innerAmount);
                advancePayBalance = Arith.add(advancePayBalance, innerAmount);
                //核销金额
                double innerWriteOffAmount = getDouble(sourceData.getString(PaySheetEnum.WRITE_OFF_AMOUNT.getAttr()));
                writeOffAmount = Arith.add(writeOffAmount, innerWriteOffAmount);
                advancePayBalance = Arith.sub(advancePayBalance, innerWriteOffAmount);
                data.put(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr(),AttrDecimalPrecisionHelper.parseThousandth(advancePayBalance,accuracy));
                //格式化回款状态ItemPojo -> text
                data.put(PaySheetEnum.PAY_SHEET_TYPE.getAttr(),commonHelp.formatFundStatusText(data,PaySheetEnum.PAY_SHEET_TYPE.getAttr(), PaySheetTypeEnum.UNKNOWN.getName()));
            }
            formDataListVO.setPaasFormDataESList(paasFormDataESList);
        }
        formDataListVO.setHeadList(newHeadList);
        PaySheetFromBalanceListVO  paySheetFromBalanceListVO = new PaySheetFromBalanceListVO();
        BeanUtil.copyProperties(formDataListVO,paySheetFromBalanceListVO);
        Map<String, Object> summary = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        summary.put(PaySheetEnum.AMOUNT.getAttr(),AttrDecimalPrecisionHelper.parseThousandth(amount,accuracy));
        summary.put(PaySheetEnum.WRITE_OFF_AMOUNT.getAttr(),AttrDecimalPrecisionHelper.parseThousandth(writeOffAmount,accuracy));
//        summary.put(PaymentBalanceEnum.ADVANCE_PAYMENT_BALANCE.getAttr(),attrDecimalPrecisionHelper.parseThousandth(advancePaymentBalance,accuracy));
        paySheetFromBalanceListVO.setSummary(summary);
        return paySheetFromBalanceListVO;
    }

    @Override
    public void getSupplementAmount(PaasFormDataEsListVO formDataListVO, String corpid) throws XbbException {
        List<Long> supplierIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for ( PaasFormDataEntityExt paasFormDataEntityExt : formDataListVO.getPaasFormDataESList() ) {
            supplierIds.add(paasFormDataEntityExt.getId());
        }
        if ( CollectionsUtil.isNotEmpty(supplierIds) ) {
            List<PayBalanceEntity> payBalanceEntityList = payBalanceModel.getBySupplierIds(supplierIds, corpid);
            Map<Long, Double> payBalanceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PayBalanceEntity item:payBalanceEntityList) {
                payBalanceMap.put(item.getSupplierId(), item.getAdvancePayBalance());
            }
            formDataListVO.getPaasFormDataESList().forEach(item-> {
                Double advancePayBalance = payBalanceMap.get(item.getId()) == null ? 0.00D : payBalanceMap.get(item.getId());
                item.setAdvancePaymentBalance(advancePayBalance);
            });
        }
    }

    @Override
    public Integer deleteBatch(List<Long> idIn, String corpid) throws XbbException {
        if(CollectionsUtil.isEmpty(idIn)){
            return 0;
        }
        Integer delete = payBalanceModel.deleteBatch(idIn, corpid);
        payBalanceUserModel.deleteBatchByParentId(idIn,corpid);
        return delete;
    }

    @Override
    public void updateRollback(List<Long> idIn, String corpid) throws XbbException {
        if(CollectionsUtil.isEmpty(idIn)){
            return;
        }
        payBalanceModel.deleteBatchRollback(idIn, corpid);
        payBalanceUserModel.deleteBatchRollbackByParentId(idIn,corpid);
    }

    @Override
    public void updatePayBalance4Del(String corpid, Set<String> errorTypeSet, Set<String> errorDataSet, Set<Long> customerIdSet, Map<Long, List<String>> prepaymentNoMap, Map<Long, List<Long>> prepaymentIdMap, List<Long> delIdList, SheetDeleteHandleRelateDTO sheetDeleteHandleRelateDTO) throws XbbException {
        //供应商id-该供应商要增加/减少的余额
        Map<Long, Double> customerIdToBalance = sheetDeleteHandleRelateDTO.getCustomerIdToBalance();
        List<String> delNoList = sheetDeleteHandleRelateDTO.getDelNoList();
        List<PayBalanceEntity> balanceList = payBalanceModel.getBySupplierIds(customerIdSet, corpid);
        Iterator<PayBalanceEntity> iterator = balanceList.iterator();
        while (iterator.hasNext()) {
            PayBalanceEntity balanceEntity = iterator.next();
            Long customerId = balanceEntity.getSupplierId();
            Double oldAdvancePaymentBalance = balanceEntity.getAdvancePayBalance();
            Double newAdvancePaymentBalance = customerIdToBalance.getOrDefault(customerId, 0D);
            Double newAmount = Arith.add(newAdvancePaymentBalance, oldAdvancePaymentBalance);
            //更新后的供应商余额小于0，则该供应商下付款单不能删除
            if(newAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfo4DelError(I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_ADVANCE_PAY_BALANCE_SUPPLIER), errorTypeSet, errorDataSet, prepaymentNoMap, prepaymentIdMap, delIdList, delNoList, customerId);
                iterator.remove();
            }
            //updateBatchByCorpidAndSupplierId方法mapper内部已经用原金额加上新的金额，因此此处把新的金额置入即可
            balanceEntity.setAdvancePayBalance(newAdvancePaymentBalance);
        }
        payBalanceModel.updateBatchByCorpidAndSupplierId(balanceList, corpid);
    }

    @Override
    public void dataConsistencyUpdateSupplier(String corpid, Long supplierId, String supplierName) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(PayBalanceEnum.SUPPLIER_ID.getAttr(), supplierId));
            List<String> fieldList = Collections.singletonList("id");
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_PAY_BALANCE, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<PayBalanceEntity> list = payBalanceModel.findEntitys(param);
            List<InsertDTO> insertList = new ArrayList<>();
            for (PayBalanceEntity entity : list) {
                InsertDTO insertDTO = new InsertDTO();
                insertDTO.setEsId(corpid + "_" + entity.getId());
                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(PayBalanceEnum.SUPPLIER_NAME.getAttr(), supplierName);
                insertDTO.setSource(map);
                insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAY_BALANCE);
                insertList.add(insertDTO);
            }
            if (insertList.size() > 0) {
                //保证更新ES是最后一行，如果不能要在catch写ES的回滚
                paasEsModel.updateBatch(insertList);
            }
        } catch (Exception e) {
            LOG.error("PayPlanSheetServiceImpl.dataConsistencyUpdateSupplier 出错，corpid=" + corpid + "  supplierId=" + supplierId + " supplierName=" + supplierName, e);
        }
    }

    @Override
    public void updateRollbackBySupplierId(Collection<Long> supplierId, String corpid) throws XbbException {
        if (CollectionUtils.isEmpty(supplierId)) {
            return;
        }
        List<PayBalanceEntity> balanceList = payBalanceModel.getBySupplierIds(supplierId, corpid);
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_PAY_BALANCE;
        if (CollectionsUtil.isNotEmpty(balanceList)) {
            //数据库数据不为空，则把数据库同步至es内
            for (PayBalanceEntity balanceEntity : balanceList) {
                InsertDTO insertDTO = payBalanceModel.getSaveDTO(balanceEntity, indexTypeEnum);
                paasEsModel.update(insertDTO);
            }
        } else {
            //数据库没有，但是es能查到，则把es内的直接删除
            BoolQueryBuilder boolQueryBuilder = chartQueryHelp.boolQueryBuilder4Base(corpid);
            List<PayBalanceEntity> result = formHelp.getFormListByIds4All(indexTypeEnum,boolQueryBuilder, "supplierId", supplierId, Collections.singletonList(BasicConstant.ID), PayBalanceEntity.class);
            if (CollectionsUtil.isNotEmpty(result)) {
                //新建失败，则直接删除es
                List<DeleteDTO> deleteUserList = new ArrayList<>();
                for (PayBalanceEntity entity : result) {
                    DeleteDTO deleteDTO = new DeleteDTO();
                    deleteDTO.setEsId(corpid + "_" + entity.getId());
                    deleteDTO.setIndexTypeEnum(indexTypeEnum);
                    deleteUserList.add(deleteDTO);
                }
                paasEsModel.physicalDeleteBatchChild(deleteUserList, corpid, indexTypeEnum);
            }
        }
    }

    /**
     * 批量删除预付款余额
     * （1）首先需要判断预付款详情里面的预付款及其核销记录为空，才能进行删除
     * (2)前置条件满足才能进行删除
     * @param formDataDeleteBatchDTO
     */
    @Override
    public List<Long> deletePayBalanceBatch(FormDataDeleteBatchDTO formDataDeleteBatchDTO) throws XbbException {
        //判断是否满足能进行删除预付款的条件
        //直接调用现成的的方法去做查询，FormDataDeleteBatchDTO转化成PaySheetFromBalanceDTO
        PaySheetFromBalanceDTO paySheetFromBalanceDTO = new PaySheetFromBalanceDTO();
        BeanUtil.copyProperties(formDataDeleteBatchDTO,paySheetFromBalanceDTO);
        //获取供应商id
        PayBalanceEntity payBalanceEntity = payBalanceModel.getById(formDataDeleteBatchDTO.getDataIdList().get(0), formDataDeleteBatchDTO.getCorpid());
        if (payBalanceEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long supplierId = payBalanceEntity.getSupplierId();
        paySheetFromBalanceDTO.setSupplierId(supplierId);
        PaySheetFromBalanceListVO paySheetFromBalanceListVO = payBalanceService.paySheetFromBalanceList(paySheetFromBalanceDTO);
        if (!ObjectUtils.isEmpty(paySheetFromBalanceListVO) && CollectionsUtil.isNotEmpty(paySheetFromBalanceListVO.getPaasFormDataESList())) {
            throw new XbbException(FundAccountErrorCodeEnum.API_ERROR_1000010);
        }
        //进行实际的预付款删除
        deleteBatch(formDataDeleteBatchDTO.getDataIdList(),formDataDeleteBatchDTO.getCorpid());
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), formDataDeleteBatchDTO.getLoginUserName(), XbbRefTypeEnum.PREPAY_BALANCE.getName(),payBalanceEntity.getSupplierName());
        mongoLogHelp.buildLog(formDataDeleteBatchDTO.getCorpid(), formDataDeleteBatchDTO.getUserId(), formDataDeleteBatchDTO.getLoginUserName(), OperateModuleTypeEnum.PayManage, OperateTypeEnum.DELETE,
                formDataDeleteBatchDTO.getDataIdList().get(0).toString(), XbbRefTypeEnum.PREPAY_BALANCE.getName(), memo, formDataDeleteBatchDTO.getHttpHeader());
        return formDataDeleteBatchDTO.getDataIdList();
    }


    private PrePaymentBalanceListPojo prePayBalanceCommonList(FormDataListDTO formDataListDTO) throws XbbException {
        if (!Objects.equals(formDataListDTO.getBusinessType(), XbbRefTypeEnum.PREPAY_BALANCE.getCode())){
            throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        String corpid =  formDataListDTO.getCorpid();
        List<ConditionsEntityExt> conditionList = formDataListDTO.getConditions();
        if(CollectionsUtil.isNotEmpty(conditionList)){
            for (ConditionsEntityExt conditionsEntityExt : conditionList) {
                if(Objects.equals(FieldTypeEnum.DATAID.getAlias(),conditionsEntityExt.getAttr())){
                    conditionsEntityExt.setAttr(FieldTypeEnum.DATAID.getDescription());
                    break;
                }
            }
        }
        saasListDataPermissionHelp.listDataPermission(conditionList, formDataListDTO.getLoginUser(), XbbRefTypeEnum.PREPAY_BALANCE.getCode(), formDataListDTO.getSubBusinessType());
        formDataListDTO.setConditions(conditionList);

        //分组条件
        List<ConditionsEntityExt> groupConditionsList = new ArrayList<>();
        formDataListDTO.getConditions().addAll(groupConditionsList);
        //表单获取
        PaasFormEntityExt form = formDataListSearchHelp.getForm(formDataListDTO);
        //解释获取以及处理
        HandleExplainPojo handleExplainPojo = formDataListSearchHelp.handlExplains(formDataListDTO,form);
        List<FieldAttrEntity> explainList = handleExplainPojo.getExplainList();
        //解释获取以及处理
//        Map<String,FieldAttrEntity> secondaryExplainMap = formDataListSearchHelp.secondaryExplains(formDataListDTO);
        //默认排序 字段显示
        formDataListSearchHelp.setListColumn(formDataListDTO);
        // 获取paas的本人及其下属的数据
        formDataListDTO.setConditions(formDataListSearchHelp.getPaasPermission(formDataListDTO));
        //模糊查询高级模式
        formDataListSearchHelp.nameLikeSupprtSet(formDataListDTO);
        //查询条件
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark());
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //nameLike的处理（右上角的搜索）
        String nameLike = formDataListDTO.getNameLike();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        if(StringUtil.isNotEmpty(nameLike)){
            BoolQueryBuilder supplierBoolQueryBuilder = boolQuery();
            //解析查询条件
            supplierBoolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            supplierBoolQueryBuilder.filter(termQuery("del", 0));
            supplierBoolQueryBuilder.should(matchPhraseQuery(SupplierEnum.getAttrConnectData(SupplierEnum.SUPPLIER_NAME), nameLike));
            supplierBoolQueryBuilder.should(matchPhraseQuery(SupplierEnum.getAttrConnectData(SupplierEnum.PHONE)+".text_2", nameLike));
            supplierBoolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
            supplierBoolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_SUPPLIER.getType()));
            SearchRequest supplierSearchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_SUPPLIER.getIndex());
            SearchSourceBuilder supplierSourceBuilder = new SearchSourceBuilder();
            List<String> fieldList = Collections.singletonList("id");
            EsUtil.setFieldList(supplierSourceBuilder, fieldList);
            //模糊关联查询最多1W
            PageRequest supplierPageRequest =  EsUtil.setPage(supplierSourceBuilder, 1,  SizeConstant.PAGE_SIZE);
            supplierSourceBuilder.query(supplierBoolQueryBuilder);
            supplierSearchRequest.source(supplierSourceBuilder);
            XbbAggregatedPage<SupplierEntityExt> supplierEntityExts =  xbbElasticsearchRestTemplate.queryForPages(supplierPageRequest, supplierSearchRequest, SupplierEntityExt.class);
            if (supplierEntityExts != null) {
                List<SupplierEntityExt> supplierResultList  = supplierEntityExts.getContent();
                List<Long> supplierIdList = new ArrayList<>(supplierResultList.size());
                for (SupplierEntityExt supplierEntityExt : supplierResultList) {
                    supplierIdList.add(supplierEntityExt.getDataId());
                }
                boolQueryBuilder.filter(termsQuery(PayBalanceEnum.SUPPLIER_ID.getAttr(),supplierIdList));
            }
        }
        SearchRequest searchRequest = paasFormDataEsModel.getSearchRequest(formDataListDTO, indexTypeEnum, sourceBuilder, boolQueryBuilder);
        //数据查询
        List<PayBalanceEntity> resultList;
        long num;
        if (Objects.equals(formDataListDTO.getFromExport(), 1)) {
            EsUtil.setPage(sourceBuilder, 1, PaasConstant.ES_MAX_PAGE_SIZE);
            resultList = xbbElasticsearchRestTemplate.getScrollListForExport(PayBalanceEntity.class, searchRequest);
            num = resultList.size();
        } else {
            //分页
            PageRequest pageRequest= EsUtil.setPage(sourceBuilder, formDataListDTO.getPage(), formDataListDTO.getPageSize());
            XbbAggregatedPage<PayBalanceEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest,PayBalanceEntity.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            resultList =  esEntities.getContent();
            num = esEntities.getTotalElements();
        }
        List<Long> supplierIdList = new ArrayList<>(resultList.size());
        Map<Long,String> supplierMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PayBalanceEntity payBalanceEntity : resultList) {
            payBalanceEntity.setDataId(payBalanceEntity.getId());
            JSONObject obj = (JSONObject) JSONObject.toJSON(payBalanceEntity);
            obj.remove("data");
            payBalanceEntity.setData(obj);
            payBalanceEntity.setSourceData(obj);
            supplierIdList.add(payBalanceEntity.getSupplierId());
            supplierMap.put(payBalanceEntity.getSupplierId(), payBalanceEntity.getSupplierName());
        }
        Map<Long,Integer> purchaseCountMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(CollectionsUtil.isNotEmpty(supplierIdList)){
            //关联合同的渲染
            purchaseCountMap  = getPurchaseCountBySupplier(corpid, supplierIdList);
        }
        //精度
        Integer accuracy = 2;
        for (FieldAttrEntity balanceExplain : explainList) {
            if(Objects.equals(balanceExplain.getAttr(), PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr())){
                accuracy = balanceExplain.getAccuracy();
                break;
            }
        }
        for (PayBalanceEntity payBalanceEntity : resultList) {
            Long supplierId = payBalanceEntity.getSupplierId();
            JSONObject obj = (JSONObject) JSONObject.toJSON(payBalanceEntity);
            obj.remove("data");
            obj.remove("sourceData");
            //把关联供应商的解析放入
            String supplierName = supplierMap.get(supplierId);
            List<LinkBusinessSinglePojo> supplierLink = getSupplierLinkBusinessSinglePojos(supplierId, supplierName);
            obj.put(PayBalanceEnum.SUPPLIER_ID.getAttr(),supplierLink);
            obj.put(PayBalanceEnum.SUPPLIER_NAME.getAttr(),supplierName);
            Integer purchaseCount = purchaseCountMap.get(supplierId);
            if(purchaseCount == null){
                purchaseCount = 0;
            }
            obj.put(PayBalanceEnum.PURCHASE_COUNT.getAttr(),purchaseCount);
            payBalanceEntity.setPurchaseCount(purchaseCount);
            Double advancePayBalance = payBalanceEntity.getAdvancePayBalance();
            Object moneyStr =  AttrDecimalPrecisionHelper.parseThousandth(advancePayBalance,accuracy);
            obj.put(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr(), moneyStr);
            payBalanceEntity.setData(obj);
        }

        //  ==================== 上部按钮权限和下部按钮权限 ====================

        PrePaymentBalanceListVO prePayBalanceListVO = new PrePaymentBalanceListVO();
        prePayBalanceListVO.setForm(form);
        formDataListSearchHelp.setButtons(formDataListDTO, prePayBalanceListVO);
        formDataListSearchHelp.explainFieldSort(formDataListDTO, explainList);

        PrePaymentBalanceListPojo prePayBalanceListPojo = new PrePaymentBalanceListPojo();
        prePayBalanceListPojo.setForm(form);
        prePayBalanceListPojo.setExplainList(explainList);
        prePayBalanceListPojo.setResultList(resultList);
        prePayBalanceListPojo.setRowsCount((int) num);
//        prePayBalanceListPojo.setSecondaryExplainMap(secondaryExplainMap);
        prePayBalanceListPojo.setTopPermissions(prePayBalanceListVO.getTopPermissions());
        prePayBalanceListPojo.setBottomPermissions(prePayBalanceListVO.getBottomPermissions());
        return prePayBalanceListPojo;
    }

    private List<LinkBusinessSinglePojo> getSupplierLinkBusinessSinglePojos(Long supplierId, String supplierName) {
        LinkBusinessSinglePojo linkBusinessSinglePojo = new LinkBusinessSinglePojo();
        linkBusinessSinglePojo.setBusinessType(XbbRefTypeEnum.SUPPLIER.getCode());
        linkBusinessSinglePojo.setId(supplierId);
        linkBusinessSinglePojo.setName(supplierName);
        linkBusinessSinglePojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
        List<LinkBusinessSinglePojo> supplierLink = new ArrayList<>(1);
        supplierLink.add(linkBusinessSinglePojo);
        return supplierLink;
    }

    /**
     * 处理预付款余额团队
     * @param supplierId 供应商id
     * @param corpid 公司id
     * @param payBalanceEntity 预付款余额实体
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void insertBalanceUser(Long supplierId, String corpid, PayBalanceEntity payBalanceEntity) throws XbbException {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(ParameterConstant.CORPID,corpid);
        map.put(BasicConstant.DATAID,supplierId);
        List<SupplierUserEntity> supplierUserList = supplierUserModel.findEntitys(map);
        if(CollectionsUtil.isNotEmpty(supplierUserList)){
            List<PayBalanceUserEntity> payBalanceUserEntityList = new ArrayList<>(supplierUserList.size());
            for (SupplierUserEntity supplierUserEntity : supplierUserList) {
                PayBalanceUserEntity  payBalanceUserEntity = new PayBalanceUserEntity();
                BeanUtil.copyProperties(supplierUserEntity,payBalanceUserEntity);
                payBalanceUserEntity.setSupplierId(supplierUserEntity.getDataId());
                payBalanceUserEntity.setDataId(payBalanceEntity.getId());
                payBalanceUserEntityList.add(payBalanceUserEntity);
            }
            payBalanceUserModel.insertBatch(payBalanceUserEntityList);
        }
    }

    private PaasFormEntityExt varifyFormAndExplain(String corpid, Long formId) throws XbbException {
        PaasFormEntityExt paasFormEntity = paasFormModel.getByKey(formId, corpid);
        if (paasFormEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (paasFormExplainEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        return paasFormEntity;
    }

    private List<DetailTabPojo> getDetailTabPojos(Integer businessType, UserVO userVO, PlatFormEnum platFormEnum, String corpid, Long formId) {
        List<BusinessDetailTabEnum> tabEnumList;
        if (Objects.equals(platFormEnum, PlatFormEnum.WEB)) {
            tabEnumList = BusinessDetailTabEnum.getByBusinessTypeAndPermission(businessType, userVO.getPermSet());
        } else {
            tabEnumList = BusinessDetailTabEnum.getByBusinessTypeAndPermissionForDingtalk(businessType, userVO.getPermSet());
        }
        List<DetailTabPojo> tabList = new ArrayList<>();
        for (BusinessDetailTabEnum tabEnum : tabEnumList) {
            DetailTabPojo detailTabPojo = new DetailTabPojo();
            BeanUtil.copyProperties(tabEnum.getAnEnum(), detailTabPojo);
            detailTabPojo.setAttr(detailTabPojo.getKey());
            tabList.add(detailTabPojo);
        }
        tabList = proDetailHandlerHelp.handleDetailTabSort(userVO.getUserId(), corpid, formId, businessType, tabList);
        return tabList;
    }

    private Integer getAccuracy(String corpid) throws XbbException {
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PREPAY_BALANCE.getCode(),corpid);
        List<FieldAttrEntity> balanceExplains = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Integer accuracy = 2;
        for (FieldAttrEntity balanceExplain : balanceExplains) {
            if(Objects.equals(balanceExplain.getAttr(), PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr())){
                accuracy = balanceExplain.getAccuracy();
                break;
            }
        }
        return accuracy;
    }

    private Map<Long,Integer> getPurchaseCountBySupplier(String corpid, List<Long> supplierIdList) throws XbbException {
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_PURCHASE;
        BoolQueryBuilder purchaseBoolQueryBuilder = boolQuery();
        purchaseBoolQueryBuilder.filter(termsQuery(PurchaseEnum.getEsAttr4Keyword(PurchaseEnum.SUPPLIER_ID), supplierIdList));
        purchaseBoolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        purchaseBoolQueryBuilder.filter(termQuery("del", 0));
        //未付款金额>0
        purchaseBoolQueryBuilder.filter(rangeQuery(PurchaseEnum.getAttrConnectData(PurchaseEnum.UN_FINISH_AMOUNT)).gt(0));
        //非红冲
//        purchaseBoolQueryBuilder.filter(termQuery(PurchaseEnum.getAttrConnectData(PurchaseEnum.IS_RED), 0));
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("agg01").field(PurchaseEnum.getEsAttr4Keyword(PurchaseEnum.SUPPLIER_ID)).size(Integer.MAX_VALUE);
        termsAggregationBuilder.executionHint(ElasticConstant.EXECUTION_HINT);
        JSONObject jsonObject = esHelper.multElasticAggs4NoBuckets2Object(indexTypeEnum, purchaseBoolQueryBuilder, Arrays.asList(termsAggregationBuilder));
        JSONArray buckets = jsonObject.getJSONObject("aggregations").getJSONObject("agg01").getJSONArray("buckets");
        Map<Long,Integer> purchaseCountMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(buckets != null && !buckets.isEmpty()){
            for (Object bucket : buckets) {
                JSONObject bucketJson = (JSONObject)bucket;
                //供应商id
                Long supplierIdKey = Long.valueOf(bucketJson.get("key").toString());
                //当前供应商下满足的采购合同的个数
                Integer  docCount= bucketJson.getInteger("doc_count");
                purchaseCountMap.put(supplierIdKey,docCount);
            }
        }
        return purchaseCountMap;
    }

    private void setWorkFlowPojo(List<WorkFlowPojo> workFlowPojoList, BusinessDetailButtonEnum businessDetailButtonEnum) {
        WorkFlowPojo workFlowPojo = new WorkFlowPojo();
        workFlowPojo.setAttr(businessDetailButtonEnum.getAnEnum().getAttr());
        workFlowPojo.setBtnType(businessDetailButtonEnum.getAnEnum().getAttr());
        workFlowPojo.setBusinessType(businessDetailButtonEnum.getLinkBusinessType());
        workFlowPojo.setValue(businessDetailButtonEnum.getAnEnum().getValue());
        workFlowPojoList.add(workFlowPojo);
    }

    private AggSumDTO getAggSumDTO(PaySheetEnum amount) {
        AggSumDTO aggSumDTO = new AggSumDTO();
        aggSumDTO.setAttr(amount.getAttr());
        aggSumDTO.setName(amount.getAttrName());
        aggSumDTO.setField("data."+amount.getAttr());
        FieldAttrEntity amountFieldAttrEntity = new FieldAttrEntity();
        amountFieldAttrEntity.setAttr(amount.getAttr());
        amountFieldAttrEntity.setAttrName(amount.getAttrName());
        amountFieldAttrEntity.setFieldType(amount.getFieldType());
        aggSumDTO.setFieldAttrEntity(amountFieldAttrEntity);
        return aggSumDTO;
    }

    private double getDouble(String s){
        if (s == null) {
            return 0D;
        }
        return Double.valueOf(s);
    }
}
